package BVRClient;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * The Blue vs Red: Arena MapUnzip Class.
 * @author Jesse Gill
 * @author Shannon Setter
 */
public class BVRC_MapUnzip
{
	private static final int BUFFER_SIZE = 2048;
	
	/**
	 * Unzip the specified map file to the specified directory.
	 * @param filename
	 * @param directory
	 * @return true if the map is unzipped to the directory, false in all other cases.
	 */
	public static boolean unzipMapToDirectory(String filename, String directory)
	{
		try
		{
			File sourceFile = new File(filename);
			
			// possible error if file can't be read
			if (!sourceFile.canRead())
				return false;
			
			ZipFile mapFile = new ZipFile(sourceFile, ZipFile.OPEN_READ);
			
			// possible error if the zip file has 0 or less entries
			if (mapFile.size() <= 0)
				return false;
			
			Enumeration<? extends ZipEntry> mapFileEntries = mapFile.entries();
			
			while (mapFileEntries.hasMoreElements())
			{
				ZipEntry entry = (ZipEntry) mapFileEntries.nextElement();
				
				if (!entry.isDirectory())
				{
					File destFile = new File(directory, entry.getName());
					
					// Make sure the parent directory exists
					File destinationParent = destFile.getParentFile();
					destinationParent.mkdirs();
					
					if (! BVRC_MapUnzip.writeEntryToFile(mapFile, entry, destFile, BUFFER_SIZE))
						return false;
				}
			}
			
			mapFile.close();
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
			
			return false;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}
	
	/**
	 * Write the specified zip file entry to a destination file.
	 * @param zipFile
	 * @param entry
	 * @param destFile
	 * @param bufferSize
	 * @return true if the file is written to the destination, false in all other cases.
	 */
	private static boolean writeEntryToFile(ZipFile zipFile, ZipEntry entry, File destFile, int bufferSize)
	{
		try
		{
			BufferedInputStream is = new BufferedInputStream(zipFile.getInputStream(entry));
			
			int currentByte;
			byte data[] = new byte[bufferSize];
			
			FileOutputStream fos = new FileOutputStream(destFile);
			BufferedOutputStream dest = new BufferedOutputStream(fos, bufferSize);
			
			while ((currentByte = is.read(data, 0, bufferSize)) != -1)
			{
				dest.write(data, 0, currentByte);
			}
			
			dest.flush();
			dest.close();
			
			is.close();
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
			
			return false;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}
}
